import time
import _thread
import json
from wifi_manager import WiFiManager
from aliyun_mqtt import AliyunMQTT
from device_manager import DeviceManager
from data_transformer import DataTransformer
from ntp_manager import NTPManager
from devices.photo_sensor import PhotoSensor
from devices.led import LED

# 全局变量
wifi_manager = None
ntp_manager = None
aliyun_mqtt = None
device_manager = None
data_transformer = None
mqtt_thread_running = False  # 用于控制MQTT线程运行状态
mqtt_thread_ready = None      # 信号量，用于线程启动同步

class MainExecutionError(Exception):
    """主执行流程错误"""
    pass

def mqtt_message_thread():
    """MQTT消息处理线程"""
    global aliyun_mqtt, mqtt_thread_running
    
    try:
        print("MQTT消息处理线程已启动")
        mqtt_thread_running = True
        # 通知主线程MQTT线程已准备就绪
        mqtt_thread_ready.release()
        
        while mqtt_thread_running and aliyun_mqtt and aliyun_mqtt.connected:
            try:
                aliyun_mqtt.check_msg()
                aliyun_mqtt.check_ping()
                time.sleep(0.1)
            except Exception as e:
                print(f"MQTT消息处理错误: {e}")
                # 如果连接断开，退出线程
                if not (aliyun_mqtt and aliyun_mqtt.connected):
                    break
                time.sleep(1)  # 短暂休眠后重试
    except Exception as e:
        print(f"MQTT线程异常: {e}")
    finally:
        mqtt_thread_running = False
        print("MQTT消息处理线程已退出")

def on_aliyun_message(topic, message):
    """处理从阿里云IoT平台收到的消息"""
    global device_manager, data_transformer
    if device_manager and data_transformer:
        try:
            command_dict = json.loads(message)
            
            # 检查是否是属性设置指令
            if "params" in command_dict:
                params = command_dict["params"]
                # 使用数据转换器将阿里云指令转换为设备操作
                actions = data_transformer.aliyun_command_to_device_action(params)
                
                # 执行每个操作
                for action in actions:
                    device_manager.execute_command(
                        action["device_name"], 
                        action["command"], 
                        action["value"]
                    )

                # 读取设备原始数据
                raw_device_data = device_manager.read_all_devices()
                actions_devices_list = [action["device_name"] for action in actions]
                for device_name in list(raw_device_data.keys()):
                    if device_name not in actions_devices_list:
                        raw_device_data.pop(device_name, None)
                # 使用数据转换器转换为阿里云格式
                aliyun_device_data = data_transformer.device_data_to_aliyun_format(raw_device_data)
                print("回应当前设备数据:", aliyun_device_data)
                # 发布转换后的数据
                import config
                if aliyun_mqtt.publish(config.TOPIC_UP, aliyun_device_data):
                    print("设备数据上报成功")
                else:
                    print("设备数据上报失败")

        except json.JSONDecodeError:
            print("指令格式错误：不是有效的JSON字符串")
        except Exception as e:
            print(f"处理指令错误: {e}")

def main():
    global wifi_manager, ntp_manager, aliyun_mqtt, device_manager, data_transformer, mqtt_thread_running, mqtt_thread_ready
    
    try:
        # 1. 初始化WiFi并连接
        wifi_manager = WiFiManager()
        if not wifi_manager.connect():
            print("WiFi连接失败，程序退出")
            return

        # 2. 同步NTP时间
        ntp_manager = NTPManager()
        ntp_manager.sync_ntp()
        if not ntp_manager.sync_success:
            print("NTP同步失败，程序退出")
            return

        # 3. 初始化阿里云MQTT（传入NTP管理器，用于获取正确时间戳）
        aliyun_mqtt = AliyunMQTT(
            on_message_callback=on_aliyun_message,
            ntp_manager=ntp_manager  # 把NTP管理器传给阿里云模块
        )

        # 4. 初始化设备管理器和数据转换器
        device_manager = DeviceManager()
        data_transformer = DataTransformer()
        
        # 5. 注册设备
        photo_sensor = PhotoSensor("photo_sensor", 26)
        led = LED("led", 10)
        
        device_manager.register_device(photo_sensor)
        device_manager.register_device(led)

        # 6. 初始化NTP同步计数器
        ntp_sync_interval = 1800  # 30分钟同步一次
        ntp_counter = 0

        while True:
            print("主循环中...")
            # 累加计数器并检查是否需要同步NTP时间
            ntp_counter += 1
            if ntp_counter >= ntp_sync_interval:
                if wifi_manager.is_connected():
                    ntp_manager.sync_ntp()
                    ntp_counter = 0  # 计数器清零

            # 检查WiFi连接状态
            if not wifi_manager.is_connected():
                print("WiFi断开，尝试重连...")
                if not wifi_manager.reconnect():
                    time.sleep(1)
                    continue
                # WiFi重连后，重新同步NTP和阿里云连接
                ntp_manager.sync_ntp()

            # 检查阿里云连接状态
            if not aliyun_mqtt.connected:
                print("阿里云连接中...")
                if not aliyun_mqtt.connect():
                    print("阿里云连接失败, 重试中...")
                    time.sleep(1)
                    continue
                print("阿里云连接成功")
                
                # 启动MQTT消息线程
                mqtt_thread_running = False
                
                # 初始化信号量并启动新线程
                mqtt_thread_ready = _thread.allocate_lock()
                mqtt_thread_ready.acquire()  # 初始时锁定信号量
                _thread.start_new_thread(mqtt_message_thread, ())
                
                # 等待MQTT消息线程启动完成
                if not mqtt_thread_ready.acquire():
                    print("MQTT消息线程启动超时")
                    raise MainExecutionError("MQTT消息线程启动超时")
                    
                print("MQTT消息线程启动成功")

            # 上报数据
            if device_manager and mqtt_thread_running:
                # 读取设备原始数据
                raw_device_data = device_manager.read_all_devices()
                # 使用数据转换器转换为阿里云格式
                aliyun_device_data = data_transformer.device_data_to_aliyun_format(raw_device_data)
                aliyun_device_data.pop("led", None)  # 不上传LED状态
                
                # 发布转换后的数据
                import config
                if aliyun_mqtt.publish(config.TOPIC_UP, aliyun_device_data):
                    print("设备数据上报成功")
                else:
                    print("设备数据上报失败")
            
            time.sleep(1)

    except KeyboardInterrupt:
        print("程序被中断")
    except MainExecutionError as e:
        print(f"程序执行错误: {str(e)}")
    except Exception as e:
        print(f"运行错误：{str(e)}")
    finally:
        # 停止MQTT线程
        mqtt_thread_running = False
        # 给线程一些时间优雅退出
        time.sleep(0.1)
        # 清理资源
        if aliyun_mqtt:
            aliyun_mqtt.disconnect()
        if wifi_manager:
            wifi_manager.disconnect()
        print("程序退出")

if __name__ == "__main__":
    main()